<?php


namespace EchoPHP\Http;

use EchoPHP\Facades\Request;
use EchoPHP\Http\Response\BinaryFileResponse;
use EchoPHP\Http\Response\JsonResponse;
use EchoPHP\Http\Response\StreamedResponse;
use EchoPHP\Support\Str;

class ResponseFactory {

    protected $view;

    protected $redirector;

    /**
     * 创建响应
     * @param string $content
     * @param int $status
     * @param array $headers
     * @return Response
     */
    public function make($content = '', $status = 200, array $headers = []) {
        return new Response($content, $status, $headers);
    }

    /**
     * 生成视图响应
     * @param $view
     * @param array $data
     * @param int $status
     * @param array $headers
     * @return Response
     * @throws \Exception
     */
    public function view($view, $data = [], $status = 200, array $headers = []) {
        return $this->make(view($view, $data), $status, $headers);
    }

    /**
     * 生成json格式响应
     * @param array $data
     * @param int $status
     * @param array $headers
     * @param int $options
     * @return JsonResponse
     * @throws \Exception
     */
    public function json($data = [], $status = 200, array $headers = [], $options = 0) {
        return new JsonResponse($data, $status, $headers, false, $options);
    }

    /**
     * 生成jsonp响应
     * @param $callback
     * @param array $data
     * @param int $status
     * @param array $headers
     * @param int $options
     * @return JsonResponse
     * @throws \Exception
     */
    public function jsonp($callback, $data = [], $status = 200, array $headers = [], $options = 0) {
        return $this->json($data, $status, $headers, $options)->setCallback($callback);
    }

    /**
     * 返回xml响应
     * @param string $content
     * @param int $status
     * @param array $headers
     * @return Response
     */
    public function xml($content = '', $status = 200, array $headers = []) {
        return $this->make($content, $status, $headers)->header('Content-Type', 'text/xml');
    }

    /**
     * 流格式相应
     * @param callable $callback
     * @param int $status
     * @param array $headers
     * @return StreamedResponse
     */
    public function stream(callable $callback, $status = 200, array $headers = []) {
        return new StreamedResponse($callback, $status, $headers);
    }

    /**
     * 流文件响应下载
     * @param $callback
     * @param null $name
     * @param array $headers
     * @param string $disposition
     * @return StreamedResponse
     */
    public function streamDownload($callback, $name = null, array $headers = [], $disposition = 'attachment') {
        $response = new StreamedResponse($callback, 200, $headers);

        if (!is_null($name)) {
            return $response->setContentDisposition($disposition, $name, $this->fallbackName($name));
        }

        return $response;
    }

    /**
     * 下载文件
     * @param $file
     * @param $name
     * @param array $headers
     * @param string $disposition
     * @return BinaryFileResponse
     */
    public function download($file, $name, array $headers = [], $disposition = 'attachment') {
        $response = new BinaryFileResponse($file, 200, $headers, true, $disposition);

        if (!is_null($name)) {
            return $response->setContentDisposition($disposition, $name, $this->fallbackName($name));
        }

        return $response;
    }

    /**
     * 直接在浏览器显示文件
     * @param $file
     * @param array $headers
     * @return BinaryFileResponse
     */
    public function file($file, array $headers = []) {
        return new BinaryFileResponse($file, 200, $headers);
    }

    /**
     * 处理返回名称
     * @param $name
     * @return mixed
     */
    protected function fallbackName($name) {
        return str_replace('%', '', Str::ascii(urlencode($name)));
    }

    /**
     * 前往目标地址
     * @param $url
     * @param int $status
     * @param array $headers
     * @return Response\RedirectResponse
     */
    public function redirectTo($url, $status = 302, array $headers = []) {
        $director = new Redirector(Request::instance());
        return $director->to($url, $status, $headers);
    }

    /**
     * 前往来源页
     * @param int $status
     * @param array $headers
     * @param null $fallback
     * @return Response\RedirectResponse
     */
    public function redirectBack($status = 302, array $headers = [], $fallback = null) {
        $director = new Redirector(Request::instance());
        return $director->back($status, $headers, $fallback);
    }

    /**
     * 刷新当前页
     * @param int $status
     * @param array $headers
     * @return Response\RedirectResponse
     */
    public function redirectRefresh($status = 302, array $headers = []) {
        $director = new Redirector(Request::instance());
        return $director->refresh($status, $headers);
    }

}